package com.sxkf.core.pay.wxpay.service.impl;

import cn.hutool.core.lang.UUID;
import com.alibaba.fastjson.JSON;
import com.sxkf.core.pay.wxpay.common.WeChatPayConstants;
import com.sxkf.core.pay.wxpay.common.WeChatRequestConstants;
import com.sxkf.core.pay.wxpay.entity.WxPayEntity;
import com.sxkf.core.pay.wxpay.service.WechatPayService;
import com.sxkf.core.pay.wxpay.util.WxPayUtil;
import com.sxkf.core.pay.wxpay.vo.*;
import com.sxkf.core.pay.wxpay.wxenum.WxPayTypeEnum;
import lombok.extern.log4j.Log4j2;
import org.jeecg.common.exception.SxkfException;
import org.jeecg.common.exception.SxkfExceptionEnum;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.HashMap;
import java.util.Map;

/**
 * @Author ZhangKeChen
 * @Date 2022/9/29
 * @Description
 */
@Log4j2
@Transactional(rollbackFor = RuntimeException.class)
@Service
public class WechatPayServiceImpl implements WechatPayService {
    @Resource
   private WxPayEntity wxPayEntity;
    @Resource
   private WxPayUtil wxPayUtil;

    /**
     * 创建订单
     * weChatCreateOrderRequestVo.type        必填：交易类型：jsapi（含小程序）、app、h5、native
     * weChatCreateOrderRequestVo.totalPrice  必填：商品金额（单位：分）
     * weChatCreateOrderRequestVo.outTradeNo  必填：商家订单号
     * weChatCreateOrderRequestVo.description 必填：商品描述（商品标题）
     * weChatCreateOrderRequestVo.notifyUrl   必填：支付回掉地址
     * weChatCreateOrderRequestVo.openId      特殊必填：支付用户的OpenId，JSAPI支付时必填
     * 关于支付结果：
     * APP支付、JSAPI支付为[预支付交易会话标识]
     * Native支付为[二维码链接]
     * H5支付为[支付跳转链接]
     */

    @Override
    public Map<String, String> createOrder(WeChatCreateOrderVO weChatCreateOrderRequestVo) {
        WeChatPayVO weChatPayRequestVo = new WeChatPayVO(weChatCreateOrderRequestVo.getTotalPrice(), weChatCreateOrderRequestVo.getOpenId());
        weChatPayRequestVo.setAppid(wxPayEntity.weChatPayAppId);
        weChatPayRequestVo.setMchid(wxPayEntity.weChatPayMchId);
        weChatPayRequestVo.setNotify_url(weChatCreateOrderRequestVo.getNotifyUrl());
        weChatPayRequestVo.setDescription(weChatCreateOrderRequestVo.getDescription());
        weChatPayRequestVo.setOut_trade_no(weChatCreateOrderRequestVo.getOutTradeNo());
        String requestData = JSON.toJSONString(weChatPayRequestVo);
        log.info("微信请求入参：{}", weChatPayRequestVo.toString());
        Map<String, String> returnMap = getPayReturnMap(WeChatRequestConstants.WeChatPOSTMethod, requestData, WxPayTypeEnum.getNameByKey(weChatCreateOrderRequestVo.getPayType()), weChatCreateOrderRequestVo.getPayType());
        return returnMap;
    }

    /**
     * 根据微信返回拼接参数返回
     *
     * @param method      请求方式
     * @param requestDate 请求数据
     * @param url         请求地址
     * @param payType     支付类型
     * @return
     */
    public  Map<String, String> getPayReturnMap(String method, String requestDate, String url, String payType) {
        HashMap<String, String> returnMap = new HashMap();
        //请求并获取返回、序列化
        WeChatPayReturnVO weChatPayResponseVo = wxPayUtil.wxHttpRequest(method, url, requestDate, WeChatPayReturnVO.class);

        if (WeChatPayConstants.WeChatPayAPP.equals(payType)) {
            //获取预支付交易会话标识
            String prepay_id = weChatPayResponseVo.getPrepay_id();
            //生成随机字符串
            String nonceStr = UUID.randomUUID().toString(true);
            //生成时间戳
            String timestamp = String.valueOf(System.currentTimeMillis() / 1000);
            //生成代签名的支付信息
            String signature = wxPayUtil.appPaySign(prepay_id, nonceStr, timestamp);
            returnMap.put("appid", wxPayEntity.weChatPayAppId);
            returnMap.put("partnerid", wxPayEntity.weChatPayMchId);
            returnMap.put("prepayid", prepay_id);
            returnMap.put("package", "Sign=WXPay");
            returnMap.put("noncestr", nonceStr);
            returnMap.put("timestamp", timestamp);
            returnMap.put("sign", signature);
            return returnMap;
        } else if (WeChatPayConstants.WeChatPayJSAPI.equals(payType)) {
            //获取预支付交易会话标识
            String prepay_id = weChatPayResponseVo.getPrepay_id();
            //生成随机字符串
            String nonceStr = UUID.randomUUID().toString(true);
            //生成时间戳
            String timestamp = String.valueOf(System.currentTimeMillis() / 1000);
            returnMap.put("appId", wxPayEntity.weChatPayAppId);
            returnMap.put("timeStamp", timestamp);
            returnMap.put("nonceStr", nonceStr);
            returnMap.put("package", "prepay_id=" + prepay_id);
            returnMap.put("signType", "RSA");
            //生成代签名的支付信息
            String signature = wxPayUtil.appPaySign(returnMap.get("package"), nonceStr, timestamp);
            returnMap.put("paySign", signature);
            return returnMap;
        } else if (WeChatPayConstants.WeChatPayNATIVE.equals(payType)) {
            //获取返回的二维码链接
            String code_url = weChatPayResponseVo.getCode_url();
            returnMap.put("code_url", code_url);
            return returnMap;
        } else if (WeChatPayConstants.WeChatPayH5.equals(payType)) {
            //获取返回的支付跳转链接
            String h5_url = weChatPayResponseVo.getH5_url();
            returnMap.put("h5_url", h5_url);
            return returnMap;
        } else {
            throw new SxkfException(SxkfExceptionEnum.PAY_TYPE_ERROR);
        }
    }

    /**
     * 退款接口
     *
     * @param weChatRefundRequestVo
     * @return wxRefundReturnInfoVo
     */
    @Override
    public WeChatRefundReturnVO refundOrder(WeChatRefundVO weChatRefundRequestVo) {
        //包装请求参数
        String requestData = JSON.toJSONString(weChatRefundRequestVo);
        //接收请求结果并序列化
        WeChatRefundReturnVO weChatRefundResponseVo = wxPayUtil.wxHttpRequest(WeChatRequestConstants.WeChatPOSTMethod, wxPayEntity.refundUrl, requestData, WeChatRefundReturnVO.class);
        return weChatRefundResponseVo;
    }

    /**
     * 查询订单
     *
     * @param transaction_id 商户系统内部订单号
     * @return notifyResourceVO
     */
    @Override
    public QueryOrderVO QueryOrder(String transaction_id) {
        //包装请求路径
        String url = String.format(wxPayEntity.queryUrl, transaction_id, wxPayEntity.weChatPayMchId);
        //接收请求结果并序列化
        QueryOrderVO queryOrderResponseVo = wxPayUtil.wxHttpRequest(WeChatRequestConstants.WeChatGETMethod, url, null, QueryOrderVO.class);
        return queryOrderResponseVo;
    }

    /**
     * 功能描述: 关闭订单
     *
     * @param out_trade_no 商户系统内部订单号
     * @return code
     */
    @Override
    public String CloseOrder(String out_trade_no) {
        //包装请求路径
        String url = String.format(wxPayEntity.closeUrl, out_trade_no);
        WeChatCloseOrderVO weChatCloseOrderVo=new WeChatCloseOrderVO();
        weChatCloseOrderVo.setMchid(wxPayEntity.weChatPayMchId);
        //接收请求结果 接口响应204，无内容  即成功
        String code = wxPayUtil.wxHttpRequest(WeChatRequestConstants.WeChatPOSTMethod, url, JSON.toJSONString(weChatCloseOrderVo), String.class);
        return code;
    }
}
